package main

import (
	"context"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"
	"time"

	"gitee.com/rw555/fdsmastergo/internal/web_api"
	"gitee.com/rw555/fdsmastergo/pkg/logger"
	"gitee.com/rw555/fdsmastergo/pkg/version"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

func main() {
	logger.Configure(logger.Config{
		EnableConsole:       true,
		EnableCaller:        true,
		LogDirByServiceName: "web_server",
		MaxSize:             1,
		MaxBackups:          3,
		MaxAge:              3,
		SystemLogLevel:      zapcore.InfoLevel,
		OperationLogLevel:   zapcore.InfoLevel,
		NetworkLogLevel:     zapcore.InfoLevel,
		OtherLogLevel:       zapcore.DebugLevel,
	})
	defer logger.Sync()

	// 输出版本信息
	vInfo := version.NewInfo("web_server")
	logger.SystemInfo("Web服务启动",
		zap.String("version", vInfo.Version),
		zap.String("gitCommit", vInfo.GitCommit),
		zap.String("buildTime", vInfo.BuildTime),
		zap.String("platform", vInfo.Platform))

	// 创建API处理器
	handler := web_api.NewHandler(nil, nil)

	// 设置 Gin 为发布模式
	gin.SetMode(gin.ReleaseMode)
	// 使用 gin.New() 替代 gin.Default()
	r := gin.New() // 添加 Recovery 中间件
	r.Use(gin.Recovery())
	// 添加自定义日志中间件
	r.Use(CustomLogger())
	// 设置可信代理
	trustedProxies := []string{"127.0.0.1"}
	if err := r.SetTrustedProxies(trustedProxies); err != nil {
		logger.SystemError("设置可信代理失败", zap.Error(err))
		return
	}

	// 获取可执行文件的路径
	execPath, err := os.Executable()
	if err != nil {
		logger.SystemError("获取可执行文件路径失败", zap.Error(err))
		return
	}

	// 获取可执行文件所在的目录
	execDir := filepath.Dir(execPath)
	logger.SystemInfo("可执行文件目录", zap.String("path", execDir))

	// 静态文件路径
	staticDir := filepath.Join(execDir, "static")
	logger.SystemInfo("静态文件目录", zap.String("path", staticDir))

	// 静态文件服务
	r.Static("/static", staticDir)
	r.StaticFile("/", filepath.Join(staticDir, "login.html"))
	r.StaticFile("/login.html", filepath.Join(staticDir, "login.html"))
	r.StaticFile("/welcome.html", filepath.Join(staticDir, "welcome.html"))
	r.StaticFile("/config.html", filepath.Join(staticDir, "config.html"))
	r.StaticFile("/monitor.html", filepath.Join(staticDir, "monitor.html"))
	r.StaticFile("/log.html", filepath.Join(staticDir, "log.html"))
	r.StaticFile("/music.html", filepath.Join(staticDir, "music.html"))
	r.StaticFile("/favicon.ico", filepath.Join(staticDir, "favicon.ico"))

	// API 路由
	api := r.Group("/api")
	{
		api.POST("/login", handler.HandleLogin)
		api.POST("/logout", handler.HandleLogout)

		// 需要管理员权限的路由
		adminApi := api.Group("/")
		adminApi.Use(handler.CheckAdminRole)
		{
			adminApi.GET("/config", handler.HandleGetConfig)
			adminApi.POST("/config", handler.HandleUpdateConfig)
		}

		// 普通路由
		api.GET("/status", handler.HandleGetStatus)
		api.POST("/mode", handler.HandleSetMode)
		api.GET("/bluetooth/devices/smoke", handler.HandleGetSmokeDevices)
		api.GET("/bluetooth/devices/personnel", handler.HandleGetPersonnelDevices)
		api.POST("/logs/:type", handler.HandleGetLogs)

		// 音频相关路由
		music := api.Group("/music")
		{
			music.GET("/list", handler.HandleMusicList)             // 获取音频列表
			music.POST("/upload", handler.HandleMusicUpload)        // 上传音频文件
			music.DELETE("/:filename", handler.HandleMusicDelete)   // 删除音频文件
			music.POST("/delete/all", handler.HandleMusicDeleteAll) // 删除全部音频文件
			music.GET("/status", handler.HandleMusicStatus)         // 获取播放状态
			music.POST("/control", handler.HandleMusicControl)      // 控制播放（播放/暂停/停止）
			music.GET("/events", handler.HandleStreamEvents)        // SSE事件流，用于实时更新播放状态

			// 播放列表相关路由
			playlists := music.Group("/playlists")
			{
				playlists.GET("", handler.HandlePlaylistsList)                   // 获取所有播放列表
				playlists.POST("", handler.HandlePlaylistCreate)                 // 创建新播放列表
				playlists.GET("/:id", handler.HandleGetPlaylist)                 // 获取指定播放列表
				playlists.PUT("/:id", handler.HandleUpdatePlaylist)              // 更新播放列表
				playlists.DELETE("/:id", handler.HandleDeletePlaylist)           // 删除播放列表
				playlists.POST("/:id/default", handler.HandleSetDefaultPlaylist) // 设置默认播放列表
				playlists.GET("/default", handler.HandleGetDefaultPlaylist)      // 获取默认播放列表

				playlists.POST("/:id/items", handler.HandlePlaylistAddItem)              // 添加项目到播放列表
				playlists.DELETE("/:id/items/:itemId", handler.HandlePlaylistRemoveItem) // 从播放列表移除项目
				playlists.DELETE("/:id/clear", handler.HandlePlaylistClear)              // 清空播放列表
				playlists.POST("/:id/load", handler.HandleLoadPlaylist)                  // 加载播放列表到播放器
			}
		}
	}

	// 创建HTTP服务器
	srv := &http.Server{
		Addr:    "0.0.0.0:8080", // 监听所有网络接口
		Handler: r,
	}

	// 在单独的goroutine中启动服务器
	go func() {
		logger.SystemInfo("Web服务器启动", zap.String("port", srv.Addr))
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			logger.SystemError("启动服务器失败", zap.Error(err))
		}
	}()

	// 等待中断信号
	quit := make(chan os.Signal, 1)
	// 监听 SIGINT (Ctrl+C) 和 SIGTERM 信号
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
	logger.SystemInfo("正在关闭服务器...")

	// 先关闭音频管理器，确保所有SSE连接优雅关闭
	logger.SystemInfo("正在关闭音频管理器...")
	handler.CloseAudioManager()
	logger.SystemInfo("音频管理器已关闭")

	// 创建一个较短的关闭超时时间，避免过长等待
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	// 优雅地关闭服务器
	if err := srv.Shutdown(ctx); err != nil {
		logger.SystemError("服务器关闭异常", zap.Error(err))
	} else {
		logger.SystemInfo("服务器HTTP连接已全部关闭")
	}

	logger.SystemInfo("服务器已安全关闭")
}

// 自定义日志中间件
func CustomLogger() gin.HandlerFunc {
	return func(c *gin.Context) {
		startTime := time.Now()

		c.Next()

		endTime := time.Now()
		latency := endTime.Sub(startTime)

		logger.NetworkInfo("HTTP Request",
			zap.String("method", c.Request.Method),
			zap.String("path", c.Request.URL.Path),
			zap.String("ip", c.ClientIP()),
			zap.Int("status", c.Writer.Status()),
			zap.Duration("latency", latency),
		)
	}
}
